package com.xnyzc.lhy.mis.service.impl.activity;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xnyzc.lhy.common.util.DateUtil;
import com.xnyzc.lhy.common.util.IDUtil;
import com.xnyzc.lhy.common.util.TokenUtil;
import com.xnyzc.lhy.mis.entity.activity.OaSysActivityDef;
import com.xnyzc.lhy.mis.entity.activity.OaSysActivityPeriod;
import com.xnyzc.lhy.mis.entity.activity.OaSysActivityReward;
import com.xnyzc.lhy.mis.entity.result.activity.ActivityInfoPeriodResult;
import com.xnyzc.lhy.mis.mapper.activity.OaSysActivityDefMapper;
import com.xnyzc.lhy.mis.mapper.activity.OaSysActivityPeriodMapper;
import com.xnyzc.lhy.mis.service.activity.IOaSysActivityPeriodService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xnyzc.lhy.mis.service.activity.IOaSysActivityRewardService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.time.*;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * <p>
 * 活动周期 服务实现类
 * </p>
 *
 * @author haoyfa
 * @since 2019-12-16
 */
@Service
@Slf4j
public class OaSysActivityPeriodServiceImpl extends ServiceImpl<OaSysActivityPeriodMapper, OaSysActivityPeriod> implements IOaSysActivityPeriodService {
    @Autowired
    OaSysActivityDefMapper oaSysActivityDefMapper;

    @Autowired
    OaSysActivityPeriodMapper oaSysActivityPeriodMapper;

    @Autowired
    IOaSysActivityRewardService iOaSysActivityRewardService;

    /**
     * 根据活动id获取状态="已结算"的活动周期
     * @param defId
     * @return
     */
    @Override
    public List<OaSysActivityPeriod> queryActivityPeriodList(Long defId) {
        QueryWrapper<OaSysActivityPeriod> activityPeriodQueryWrapper = new QueryWrapper<OaSysActivityPeriod>();
        activityPeriodQueryWrapper.eq(OaSysActivityPeriod.DEFID, defId);
        activityPeriodQueryWrapper.eq(OaSysActivityPeriod.STATUS, "04");

        return oaSysActivityPeriodMapper.selectList(activityPeriodQueryWrapper);
    }

    /**
     * 根据活动id获取状态="已结算"的活动周期Result
     * @param defId
     * @return
     */
    @Override
    public List<ActivityInfoPeriodResult> queryActivityPeriodResultList(Long defId) {
        List<OaSysActivityPeriod> activityPeriodList = this.queryActivityPeriodList(defId);

        if(activityPeriodList != null
                && activityPeriodList.size() >= 0){
            List<ActivityInfoPeriodResult> activityInfoPeriodResultList = new ArrayList<ActivityInfoPeriodResult>(activityPeriodList.size());
            for (OaSysActivityPeriod activityPeriod : activityPeriodList) {
                ActivityInfoPeriodResult activityInfoPeriodResult = new ActivityInfoPeriodResult();
                //ID
                activityInfoPeriodResult.setId(activityPeriod.getId().toString());
                //周期编号
                activityInfoPeriodResult.setPeriod(activityPeriod.getPeriod().toString());
                //周期状态
                activityInfoPeriodResult.setStatus(activityPeriod.getStatus());
                //开始时间
                if(activityPeriod.getBeginTime() != null) {
                    activityInfoPeriodResult.setBeginTime(activityPeriod.getBeginTime().toString());
                }
                //结束时间
                if(activityPeriod.getEndTime() != null) {
                    activityInfoPeriodResult.setEndTime(activityPeriod.getEndTime().toString());
                }
                //开始日期
                if(activityPeriod.getBeginDate() != null) {
                    activityInfoPeriodResult.setBeginDate(activityPeriod.getBeginDate().toString());
                }
                //结束日期
                if(activityPeriod.getEndDate() != null) {
                    activityInfoPeriodResult.setEndDate(activityPeriod.getEndDate().toString());
                }

                activityInfoPeriodResultList.add(activityInfoPeriodResult);
            }

            return activityInfoPeriodResultList;
        }
        else {
            return null;
        }
    }

    /**
     * 根据活动定义创建活动周期
     * @param createDate
     * @param oaSysActivityDef
     */
    @Override
    public void createActivityPeriod(Date createDate, OaSysActivityDef oaSysActivityDef){
        Date startDate = oaSysActivityDef.getBeginTime();
        Date endDate = oaSysActivityDef.getEndTime();
        Integer dateNumber = oaSysActivityDef.getDateNumber();
        Integer periodNo = 1;

        //计算第1期的结束时间
        Date periodEndDate = this.calPeriodDate(oaSysActivityDef.getBeginTime(), dateNumber, periodNo);

        do {
            //创建活动周期
            this.createActivityPeriod(createDate, oaSysActivityDef, startDate, periodEndDate, periodNo);

            //下一期开始
            periodNo++;
            //下一期开始时间
            startDate = this.calDate(periodEndDate, 1);
            //下一期结束时间
            periodEndDate = this.calPeriodDate(oaSysActivityDef.getBeginTime(), dateNumber, periodNo);
        } while(periodEndDate.compareTo(endDate) <= 0);//如果下一期结束时间<=活动结束时间，创建活动周期
    }

    /**
     * 活动周期开始
     */
    @Override
    public void beginActivityPeriod(){
        //查询活动定义
        QueryWrapper<OaSysActivityPeriod> osSysActivityPeriodQueryWrapper = new QueryWrapper<OaSysActivityPeriod>();

        //状态=未开始
        osSysActivityPeriodQueryWrapper.eq(OaSysActivityPeriod.STATUS, "00");
        //活动开始日期<=当前日期
        osSysActivityPeriodQueryWrapper.le(OaSysActivityPeriod.BEGIN_DATE, new Date());
        //活动开始时间<=当前时间
        SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss");
        osSysActivityPeriodQueryWrapper.le(OaSysActivityPeriod.BEGIN_TIME, df.format(new Date()));
        //未删除
        osSysActivityPeriodQueryWrapper.eq(OaSysActivityPeriod.DELETED, 0);

        //查询数据
        List<OaSysActivityPeriod> oaSysActivityPeriodList = oaSysActivityPeriodMapper.selectList(osSysActivityPeriodQueryWrapper);

        if(oaSysActivityPeriodList != null
                && oaSysActivityPeriodList.size() >= 0){
            for (OaSysActivityPeriod oaSysActivityPeriod : oaSysActivityPeriodList) {
                //设置状态=生效中
                oaSysActivityPeriod.setStatus("01");
                oaSysActivityPeriodMapper.updateById(oaSysActivityPeriod);
            }
        }
    }

    /**
     * 活动周期结束
     */
    @Override
    public void endActivityPeriod(){
        //查询活动定义
        QueryWrapper<OaSysActivityPeriod> osSysActivityPeriodQueryWrapper = new QueryWrapper<OaSysActivityPeriod>();

        //状态=已生效
        osSysActivityPeriodQueryWrapper.eq(OaSysActivityPeriod.STATUS, "01");
        //活动结束日期<=当前日期
        osSysActivityPeriodQueryWrapper.le(OaSysActivityPeriod.END_DATE, DateUtil.getStringDateShort(new Date()));
        //活动结束时间<=当前时间
        SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss");
        osSysActivityPeriodQueryWrapper.le(OaSysActivityPeriod.END_TIME, df.format(new Date()));
        //未删除
        osSysActivityPeriodQueryWrapper.eq(OaSysActivityPeriod.DELETED, 0);

        //查询数据
        List<OaSysActivityPeriod> oaSysActivityPeriodList = oaSysActivityPeriodMapper.selectList(osSysActivityPeriodQueryWrapper);

        if(oaSysActivityPeriodList != null
                && oaSysActivityPeriodList.size() >= 0){
            for (OaSysActivityPeriod oaSysActivityPeriod : oaSysActivityPeriodList) {
                //设置状态=已结束
                oaSysActivityPeriod.setStatus("02");
                oaSysActivityPeriodMapper.updateById(oaSysActivityPeriod);
            }
        }
    }

    /**
     * 活动周期完成
     */
    @Override
    @Transactional
    public void completeActivityPeriod() {
        //查询活动周期
        QueryWrapper<OaSysActivityPeriod> osSysActivityPeriodQueryWrapper = new QueryWrapper<OaSysActivityPeriod>();

        //状态=已结束
        osSysActivityPeriodQueryWrapper.eq(OaSysActivityPeriod.STATUS, "02");
        //未删除
        osSysActivityPeriodQueryWrapper.eq(OaSysActivityPeriod.DELETED, 0);

        //查询数据
        List<OaSysActivityPeriod> oaSysActivityPeriodList = oaSysActivityPeriodMapper.selectList(osSysActivityPeriodQueryWrapper);

        if(oaSysActivityPeriodList != null
                && oaSysActivityPeriodList.size() >= 0){
            for (OaSysActivityPeriod oaSysActivityPeriod : oaSysActivityPeriodList) {
                //获取活动定义
                OaSysActivityDef oaSysActivityDef = oaSysActivityDefMapper.selectById(oaSysActivityPeriod.getDefId());
                //创建活动奖励记录
                iOaSysActivityRewardService.createActivityReward(oaSysActivityPeriod, oaSysActivityDef.getCity(), oaSysActivityDef.getWithinDate());

                //设置状态=已完成
                oaSysActivityPeriod.setStatus("03");
                oaSysActivityPeriodMapper.updateById(oaSysActivityPeriod);
            }
        }
    }

    /**
     * 活动周期结算
     */
    @Override
    @Transactional
    public void calActivityPeriodReward() {
        //查询活动周期
        QueryWrapper<OaSysActivityPeriod> osSysActivityPeriodQueryWrapper = new QueryWrapper<OaSysActivityPeriod>();

        Date now = new Date();
        //状态=已完成
        osSysActivityPeriodQueryWrapper.eq(OaSysActivityPeriod.STATUS, "03");
        //预计结算时间<=当前时间
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        osSysActivityPeriodQueryWrapper.le(OaSysActivityPeriod.CALDATEPRE, formatter.format(now));
        //未删除
        osSysActivityPeriodQueryWrapper.eq(OaSysActivityPeriod.DELETED, 0);

        //查询数据
        List<OaSysActivityPeriod> oaSysActivityPeriodList = oaSysActivityPeriodMapper.selectList(osSysActivityPeriodQueryWrapper);

        if(oaSysActivityPeriodList != null
                && oaSysActivityPeriodList.size() >= 0){
            for (OaSysActivityPeriod oaSysActivityPeriod : oaSysActivityPeriodList) {
                //获取活动奖励记录
                List<OaSysActivityReward> oaSysActivityRewardList = iOaSysActivityRewardService.queryActivityRewardList(oaSysActivityPeriod.getId());

                //结算司机奖励
                if(oaSysActivityRewardList != null
                        && oaSysActivityRewardList.size() > 0){
                    iOaSysActivityRewardService.calDriverReward(oaSysActivityRewardList);
                }

                //设置状态=已结算
                oaSysActivityPeriod.setStatus("04");
                oaSysActivityPeriod.setCalDate(now);
                oaSysActivityPeriodMapper.updateById(oaSysActivityPeriod);
            }
        }
    }

    /**
     * 计算活动周期的结束日期
     * @param startDate 开始日期
     * @param dateNumber 每一次天数
     * @param periodNo 周期编号
     * @return
     */
    private Date calPeriodDate(Date startDate, Integer dateNumber, Integer periodNo){
        return  this.calDate(startDate,dateNumber * periodNo - 1);
    }

    /**
     * 计算活动周期的结束日期
     * @return
     */
    private Date calDate(Date startDate, Integer number){
        Calendar cal = Calendar.getInstance();
        cal.setTime(startDate);
        cal.add(Calendar.DATE, number);
        return cal.getTime();
    }



    /**
     * 创建活动周期
     * @param createDate
     * @param oaSysActivityDef
     * @param startDate
     * @param endDate
     * @param periodNo
     */
    private void createActivityPeriod(Date createDate, OaSysActivityDef oaSysActivityDef, Date startDate, Date endDate, Integer periodNo){
        OaSysActivityPeriod oaSysActivityPeriod = new OaSysActivityPeriod();
        LocalTime effectiveTimeStart = oaSysActivityDef.getEffectiveTimeStart();
        LocalTime effectiveTimeEnd = oaSysActivityDef.getEffectiveTimeEnd();

        oaSysActivityPeriod.setBeginDate(this.convertLocalDate(startDate));
        oaSysActivityPeriod.setEndDate(this.convertLocalDate(endDate));
        oaSysActivityPeriod.setPeriod(periodNo);

        //状态=00未开始
        oaSysActivityPeriod.setStatus("00");
        oaSysActivityPeriod.setBeginTime(effectiveTimeStart);
        oaSysActivityPeriod.setEndTime(effectiveTimeEnd);

        //计算活动周期预计结算时间
        Date calDatePre = this.calActivityPeriodRewardDate(oaSysActivityPeriod, oaSysActivityDef);
        if(calDatePre != null){
            oaSysActivityPeriod.setCalDatePre(calDatePre);
        }

        oaSysActivityPeriod.setDefId(oaSysActivityDef.getId());
        Long defId = IDUtil.nextId();
        oaSysActivityPeriod.setId(defId);
        oaSysActivityPeriod.setCreateTime(createDate);
        oaSysActivityPeriod.setCreateUser(TokenUtil.getTokenUserId());
        oaSysActivityPeriod.setDeleted(0);
        oaSysActivityPeriod.setVersion(0L);
        oaSysActivityPeriod.setUpdateTime(createDate);

        oaSysActivityPeriodMapper.insert(oaSysActivityPeriod);
    }

    /**
     * 计算活动周期预计结算时间
     * @param oaSysActivityPeriod 活动周期
     * @param oaSysActivityDef 活动定义
     * @return
     */
    private Date calActivityPeriodRewardDate(OaSysActivityPeriod oaSysActivityPeriod, OaSysActivityDef oaSysActivityDef){
        if(oaSysActivityPeriod == null
                || oaSysActivityDef == null){
            return null;
        }

        LocalDate periodEndDate = oaSysActivityPeriod.getEndDate();
        LocalTime balance_time = oaSysActivityDef.getBalanceTime();
        Integer weekNumber = oaSysActivityDef.getBalanceWeek();

        Date calDatePre = null;
        switch (oaSysActivityDef.getBalanceType()) {
            case "00":
                //00=次日发放:周期结束日期+1天
                if(periodEndDate != null
                    && balance_time != null) {
                    calDatePre =  Date.from(periodEndDate.plusDays(1).atTime(balance_time).atZone(ZoneId.systemDefault()).toInstant());
                }
                break;
            case "01":
                //01=次周发放
                if(periodEndDate != null
                        && balance_time != null
                        && weekNumber != null) {
                    Calendar cal = DateUtil.getCalendar();
                    cal.setFirstDayOfWeek(Calendar.MONDAY);
                    cal.setTime(Date.from(periodEndDate.atStartOfDay(ZoneId.systemDefault()).toInstant()));
                    cal.set(Calendar.DAY_OF_WEEK, cal.getFirstDayOfWeek() + (weekNumber - 1));
                    cal.set(Calendar.HOUR_OF_DAY, balance_time.getHour());
                    cal.set(Calendar.MINUTE, balance_time.getMinute());
                    cal.set(Calendar.SECOND, balance_time.getSecond());
                    calDatePre = cal.getTime();
                }
                break;
            default:
                break;
        }

        return calDatePre;
    }


    /**
     * Date->LocalDate
     * @param date
     * @return
     */
    private LocalDate convertLocalDate(Date date){
        Instant instant = date.toInstant();
        ZoneId zone = ZoneId.systemDefault();
        LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, zone);
        return localDateTime.toLocalDate();
    }
}
